import { isObject } from '@/shared'
import { publicInstanceProxyHandlers } from './componentPublicInstance'
import { initProps } from './componentProps'
import { shallowReadonly } from '@/reactivity'
import { emit } from './componentEmits'
import { initSlots } from './componentSlots'

export function createComponentInstance(vnode) {
  const component = {
    vnode: vnode,
    type: vnode.type,
    setupState: {},
    proxy: null,
    props: {},
    slots: {},
    emit: () => {}
  }
  component.emit = emit.bind(null, component) as any
  return component
}

export function setupComponent(instance) {
  // setup props
  initProps(instance, instance.vnode.props)
  initSlots(instance, instance.vnode.children)
  // setup slots
  setupStatefulComponent(instance)
}
function setupStatefulComponent(instance: any) {
  const component = instance.type

  instance.proxy = new Proxy({ _: instance }, publicInstanceProxyHandlers)
  const { setup } = component
  const { props, emit } = instance
  if (setup) {
    const setupResult = setup(shallowReadonly(props), { emit })
    handleSetupResult(instance, setupResult)
  }
}
function handleSetupResult(instance: any, setupResult: any) {
  if (isObject(setupResult)) {
    instance.setupState = setupResult
  }
  finishComponentSetup(instance)
}
function finishComponentSetup(instance: any) {
  const component = instance.type
  if (component.render) {
    instance.render = component.render
  }
}
